//The includes file contains definitions for the structures,
//inputs and outputs used by the material shader
#include "Structures/Material.inc"
#include "Structures/PointLight.inc"
#include "Structures/AmbientLight.inc"
#include "Structures/DirectionalLight.inc"
#include "Structures/Fog.inc"
#include "Structures/BeamLight.inc"


//#region Shared Settings
shared float4x4 View;
shared float4x4 Projection;
shared float3 EyePosition;		// in world space

shared sFog Fog;

shared sAmbientLight AmbientLight;

shared sDirectionalLight DirectionalLight;

shared sPointLight PointLights[1];

shared sBeamLight BeamLights[1];
//#endregion


//#region Settings
float4x4 World;

sMaterial Material;
//#endregion


//#region Shader IO Structures
struct Vertex
{
    float4 Position : POSITION0;
	float3 Normal : NORMAL0;
};

struct Pixel
{
	float4 Position : POSITION0;
	float4 WorldPosition : TEXCOORD0;
	float3 WorldNormal : TEXCOORD1;
	float4 Color : COLOR0;
};
//#endregion


//#region Vertex Shaders
Pixel AmbientVS(Vertex input)
{
    Pixel output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    output.WorldPosition.xyz = worldPosition.xyz;
	output.WorldNormal = normalize(mul(input.Normal, World));
	
	output.WorldPosition.w = Fog_ComputeFactor(Fog, length(EyePosition - worldPosition));
	output.Color.rgb = Material.DiffuseColor * AmbientLight.Color + Material.EmissiveColor;
	output.Color.a = Material.Alpha;
	
    return output;
}

Pixel BasicVS(Vertex input)
{
	Pixel output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    output.WorldPosition.xyz = worldPosition.xyz;
	output.WorldNormal = normalize(mul(input.Normal, World));
	
	output.WorldPosition.w = Fog_ComputeFactor(Fog, length(EyePosition - worldPosition));
	output.Color.rgb = 0;
	output.Color.a = Material.Alpha;
	
    return output;
}

Pixel ShadowVS(Vertex input)
{
	Pixel output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    output.WorldPosition = worldPosition;
	output.WorldNormal = 0;
	
	//output.Color.rgb = Material.DiffuseColor;
	output.Color = 0;
	output.Color.a = Material.Alpha;
	
    return output;
}
//#endregion


//#region Pixel shaders
float4 BasicPS(Pixel input) : COLOR0
{
	float4 color = input.Color;
	return color;
}

float4 AmbientPS(Pixel input) : COLOR0
{
	float4 color = input.Color;
	color.rgb = Fog_ComputeColor(Fog, color.rgb, input.WorldPosition.w);
	return color;
}

float4 PointLightPS(Pixel input) : COLOR0 
{
	float4 color = 0;
	float3 directionToCamera = normalize(EyePosition - input.WorldPosition);
	color.rgb += PointLight_ComputeColor(PointLights[0], Material, input.WorldPosition, input.WorldNormal, directionToCamera);
	color.rgb = Fog_ComputeColor(Fog, color.rgb, input.WorldPosition.w);
	color.a = 1;
    return color;
}

float4 BeamLightPS(Pixel input) : COLOR0 
{
    float4 color = 0;
	float3 directionToCamera = normalize(EyePosition - input.WorldPosition);
	color.rgb += BeamLight_ComputeColor(BeamLights[0], Material, input.WorldPosition, input.WorldNormal, directionToCamera);
	color.rgb = Fog_ComputeColor(Fog, color.rgb, input.WorldPosition.w);
	color.a = 1;
    return color;
}

float4 DirectionalLightPS(Pixel input) : COLOR0
{
	float4 color;
	color.rgb = DirectionalLight_ComputeColor(DirectionalLight, Material, input.WorldPosition, input.WorldNormal, normalize(EyePosition - input.WorldPosition));
	color.rgb = Fog_ComputeColor(Fog, color.rgb, input.WorldPosition.w);
	color.a = 1;
    return color;
}
//#endregion


//#region Techniques
Technique SwitchEffect
{
	Pass Shadow
	{
		DestBlend = 6;
        SrcBlend = 5;
		VertexShader = compile vs_2_0 ShadowVS();
        PixelShader = compile ps_2_0 BasicPS();
	}
	
    Pass Ambient
    {
		DestBlend = 6;
        SrcBlend = 5;
        VertexShader = compile vs_2_0 AmbientVS();
        PixelShader = compile ps_2_0 AmbientPS();
    }
	
	Pass PointLight
    {
		DestBlend = 2;
		SrcBlend = 2;
        VertexShader = compile vs_2_0 BasicVS();
        PixelShader = compile ps_2_0 PointLightPS();
    }
	
	Pass BeamLight
	{
		DestBlend = 2;
		SrcBlend = 2;
        VertexShader = compile vs_2_0 BasicVS();
        PixelShader = compile ps_2_0 BeamLightPS();
	}
	
	Pass DirectionalLight
	{
		DestBlend = 2;
		SrcBlend = 2;
        VertexShader = compile vs_2_0 BasicVS();
        PixelShader = compile ps_2_0 DirectionalLightPS();
	}
}
//#endregion
